﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web.UI;
using Medianamik.Core;
using System.Web.UI.WebControls;
using Medianamik.Core.Configuration;
using Medianamik.Core.Sugar;

namespace Medianamik.UI.Controls
{
    public class MedianamikPropertyControl : CompositeControl
    {
        public event EventHandler SelectedIndexChanged;
        private static readonly MedianamikConfigSection Config = (MedianamikConfigSection)ConfigurationManager.GetSection(ConfigurationSectionName.MEDIANAMIK);

        private MedianamikFormTemplate _medianamikForm;
        public MedianamikFormTemplate MedianamikForm
        {
            get
            {
                if (_medianamikForm == null)
                {
                    Control parent = this;

                    do
                    {
                        parent = parent.Parent;
                    }
                    while (parent != null && parent.GetType() != typeof(MedianamikFormTemplate));

                    if (parent == null || parent.GetType() != typeof(MedianamikFormTemplate))
                    {
                        throw new Exception("MedianamikPropertyControl must be placed inside a MedianamikFormTemplate.");
                    }

                    _medianamikForm = (MedianamikFormTemplate)parent;
                }

                return _medianamikForm;
            }
        }

        public bool DisplayLabel
        {
            get
            {
                var o = ViewState["DisplayLabel"];

                if (o == null)
                    return true;

                return (bool)o;
            }
            set { ViewState["DisplayLabel"] = value; }
        }

        public bool? IsRequired
        {
            get
            {
                var o = ViewState["IsRequired"];

                return (o == null) ? default(bool?) : (bool)o;
            }
            set { ViewState["IsRequired"] = value; }
        }

        public string PropertyName
        {
            get
            {
                var o = ViewState["PropertyName"];

                if (o == null)
                    throw new ArgumentNullException("PropertyName must be defined.");

                return (string)o;
            }
            set { ViewState["PropertyName"] = value; }
        }

        public IEnumerable<string> CultureNames
        {
            get
            {
                var o = ViewState["CultureName"];
                return o == null ? new List<string> { MedianamikForm.EditionCulture.Name } :
                    o.ToString().Split(',').AsEnumerable();
            }
            set { ViewState["CultureName"] = value.ToString(","); }
        }

        public IDictionary<String, Object> Values
        {
            get
            {
                IDictionary<String, Object> values = new Dictionary<String, Object>();

                foreach (Control control in Controls)
                {
                    values.Add(((IMedianamikControl)control).EditionCultureName,
                        ((IMedianamikControl)control).GetValue());
                }

                return values;
            }
        }

        public object GetValue(string cultureName)
        {
            if (Values.Keys.Any(k => k == ""))
                return Values[""];

            return Values[cultureName];
        }

        public bool AutoGenerateValidators
        {
            get
            {
                object o = ViewState["AutoGenerateValidators"];
                if (o == null)
                {
                    return true && MedianamikForm.AutoGenerateValidators;
                }
                return (bool)o && MedianamikForm.AutoGenerateValidators;
            }
            set { ViewState["AutoGenerateValidators"] = value; }
        }

        public bool EnableClientScriptValidation
        {
            get
            {
                object o = ViewState["EnableClientScriptValidation"];
                if (o == null)
                {
                    return true && MedianamikForm.EnableClientScriptValidation;
                }
                return (bool)o && MedianamikForm.EnableClientScriptValidation;
            }
            set { ViewState["EnableClientScriptValidation"] = value; }
        }

        public bool HideMultiLingualControls
        {
            get
            {
                object o = ViewState["HideMultiLingualControls"];
                if (o == null)
                    return default(bool);
                return (bool)o;
            }
            set { ViewState["HideMultiLingualControls"] = value; }
        }

        public bool HideNeutralLanguageIndication
        {
            get
            {
                object o = ViewState["HideNeutralLanguageIndication"];
                if (o == null) return MedianamikForm.HideNeutralLanguageIndication;
                return (bool)o;
            }
            set { ViewState["HideNeutralLanguageIndication"] = value; }
        }

        public string Label
        {
            get
            {
                var o = ViewState["Label"];

                if (o == null)
                    return String.Empty;

                return (string)o;
            }
            set { ViewState["Label"] = value; }
        }

        public string ControlId
        {
            get
            {
                var o = ViewState["ControlId"];

                if (o == null)
                    return String.Empty;

                return (string)o;
            }
            set { ViewState["ControlId"] = value; }
        }

        protected string[] PropertyIds
        {
            get
            {
                if (_propertyIds == null && ViewState["PropertyIds"] != null)
                {
                    _propertyIds = (string[])ViewState["PropertyIds"];
                }
                return _propertyIds;
            }
            set
            {
                _propertyIds = value;
                ViewState["PropertyIds"] = _propertyIds;
            }
        }
        string[] _propertyIds;

        public string LabelExtensionText
        {
            get
            {
                var o = ViewState["LabelExtensionText"];

                if (o == null)
                    return String.Empty;

                return (string)o;
            }
            set { ViewState["LabelExtensionText"] = value; }
        }

        public string LabelLanguageExtensionText
        {
            get
            {
                var o = ViewState["LabelLanguageExtensionText"];

                if (o == null)
                    return String.Empty;

                return (string)o;
            }
            set { ViewState["LabelLanguageExtensionText"] = value; }
        }

        protected string MedianamikControlType
        {
            get { return ViewState["MedianamikControlType"] as string; }
            set { ViewState["MedianamikControlType"] = value; }
        }

        public override void DataBind()
        {
            base.OnDataBinding(EventArgs.Empty);

            // Create the control hierarchy.  First, clear out the child controls
            Controls.Clear();
            ClearChildViewState();
            TrackViewState();

            // Create the control hierarchy
            CreateControlHierarchy(true);

            // Mark the hierarchy as having been created
            ChildControlsCreated = true;
        }

        protected override void CreateChildControls()
        {
            // Clear out the control hiearchy
            Controls.Clear();

            //Créer la hierarchie seulement si le ViewState des Enfants est disponible
            if (MedianamikControlType != null)
            {
                CreateControlHierarchy(false /*Do Not Use DataSource*/);
            }

            ClearChildViewState();
        }

        protected virtual void CreateControlHierarchy(bool pUseDataSource)
        {
            var dataSource = MedianamikForm.DataSource as Node;

            if (pUseDataSource && dataSource != null)
            {
                var properties = new List<NodeProperty>();

                if (dataSource.NodeType.IsLanguageNeutral)
                {
                    CultureNames = new[] { "" };

                    if (dataSource.Instances.Count == 0)
                    {
                        dataSource.AddNodeInstance("");
                    }

                    properties.Add(dataSource.Instances[0].Properties[PropertyName]);
                }
                else
                {
                    var cultureNames = CultureNames.Where(c => c != "").ToList();

                    if (cultureNames.Count() == 0)
                    {
                        CultureNames = new[] { Config.DefaultEditionCultureName };
                    }
                    else
                    {
                        CultureNames = cultureNames;
                    }

                    foreach (var cultureName in CultureNames)
                    {
                        if (!dataSource.Instances.Exists(cultureName))
                        {
                            dataSource.AddNodeInstance(cultureName);
                        }

                        properties.Add(dataSource.Instances[cultureName].Properties[PropertyName]);
                    }
                }

                var propertyIds = new List<string>();

                for (var i = 0; i < properties.Count; i++)
                {
                    var id = properties[i].NodeTypePropertyID.ToString("N");

                    if (CultureNames.Count() > 1)
                    {
                        LabelLanguageExtensionText = String.Format(" ({0})",
                            properties[i].Culture.DisplayName.Substring(0,
                            properties[i].Culture.DisplayName.IndexOf(' ')).ToLower());
                        id = "prop" + i;
                    }

                    Control control;

                    if (ControlId.Length > 0)
                    {
                        control = properties[i].GetMedianamikControl(EnableClientScriptValidation,
                            AutoGenerateValidators, "", DisplayLabel, Label, LabelLanguageExtensionText,
                            LabelExtensionText, HideMultiLingualControls, HideNeutralLanguageIndication, 
                            new Guid(ControlId), IsRequired).Control;
                    }
                    else
                    {
                         control = properties[i].GetMedianamikControl(EnableClientScriptValidation,
                            AutoGenerateValidators, "", DisplayLabel, Label, LabelLanguageExtensionText,
                            LabelExtensionText, HideMultiLingualControls, HideNeutralLanguageIndication, IsRequired).Control;
                    }

                    control.ID = id;
                    propertyIds.Add(id);
                    Controls.Add(control);
                    (control as BaseMedianamikControl).CssClass = CssClass;
                    (control as BaseMedianamikControl).ValidationGroupName = MedianamikForm.ValidationGroup;
                    control.DataBind();

                    if (i == 0) MedianamikControlType = control.GetType().AssemblyQualifiedName;
                }

                PropertyIds = propertyIds.ToArray();
            }
            else
            {
                for (var i = 0; i < CultureNames.Count(); i++)
                {
                    var control = new ObjectBuilder(MedianamikControlType)
                        .GetInstance<IMedianamikControl>().Control;
                    control.ID = PropertyIds[i];
                    Controls.Add(control);
                }
            }
        }

        protected override bool OnBubbleEvent(object source, EventArgs e)
        {
            var handled = false;

            if (e is CommandEventArgs)
            {
                var ce = (CommandEventArgs)e;

                if (ce.CommandName == "SelectedIndexChanged")
                {
                    OnSelectedIndexChanged(ce);
                    handled = true;
                }
            }
            return handled;
        }

        protected virtual void OnSelectedIndexChanged(EventArgs e)
        {
            if (SelectedIndexChanged != null)
            {
                SelectedIndexChanged(this, e);
            }
        }

        public override void RenderBeginTag(HtmlTextWriter writer)
        {

        }
        public override void RenderEndTag(HtmlTextWriter writer)
        {
        }
    }
}